package proj2501.image_viewer;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageInputStream;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ImagePanel extends JPanel {
	private File sourceFile;
	private boolean isImageLoaded = false;
	private BufferedImage sourceImage;
	
	public void open(String path) {
		File file = new File(path).getAbsoluteFile();
		System.out.println("Opening a file: " + file.getPath());
		boolean failedToRead = false;
		BufferedImage image = null;
		try {
			image = ImageIO.read(file);
		} catch (IOException e1) {
			failedToRead = true;
		}
		if (image == null) {
			failedToRead = true;
		}
		if (failedToRead) {
			JOptionPane.showMessageDialog(this, "Failed to read.");
		} else {
			sourceFile = file;
			sourceImage = image;
			isImageLoaded = true;
		}
		readMetadata();
		this.repaint();
	}
	
	// TODO: Test.
	private boolean readMetadata() {
		Iterator<ImageReader> iter = ImageIO.getImageReadersByFormatName("jpeg");
		ImageReader reader = (ImageReader) iter.next();
		FileInputStream fis;
		try {
			fis = new FileInputStream(sourceFile);
		} catch (FileNotFoundException e) {
			System.out.println("readMetadata() - Failed.");
			return false;
		}
		ImageInputStream iis;
		try {
			iis = ImageIO.createImageInputStream(fis);
		} catch (IOException e) {
			System.out.println("readMetadata() - Failed.");
			return false;
		}
		reader.setInput(iis, true);
		IIOMetadata metadata;
		try {
			metadata = reader.getImageMetadata(0);
		} catch (IOException e) {
			System.out.println("readMetadata() - Failed.");
			return false;
		}
		LinkedList<String> metadataFormatNames = new LinkedList<String>(Arrays.asList(metadata.getMetadataFormatNames()));
		String metadataFormatName;
		for (int i = 0; i < metadataFormatNames.size(); i++) {
			metadataFormatName = metadataFormatNames.get(i);
			System.out.println("metadataFormatName[" + i + "]: " + metadataFormatName);
		}
		if (metadataFormatNames.contains("javax_imageio_jpeg_image_1.0")) {
			IIOMetadataNode rootNode = (IIOMetadataNode)metadata.getAsTree("javax_imageio_jpeg_image_1.0");
			MetadataNodes children = new MetadataNodes(rootNode.getChildNodes());
			for (IIOMetadataNode node: children) {
				System.out.println("Node Name: " + node.getNodeName());
				System.out.println("Node Value: " + node.getNodeValue());
				NamedNodeMap attributes = node.getAttributes();
				int length = attributes.getLength();
				for (int i = 0; i < length; i++) {
					Node attNode = attributes.item(i);
					System.out.println("Att Node Name: " + attNode.getNodeName());
					System.out.println("Att Node Value: " + attNode.getNodeValue());
				}
			}
		}
		return true;
	}
	
	private static class MetadataNodes extends LinkedList<IIOMetadataNode> {
		public MetadataNodes(NodeList nodeList) {
			int length = nodeList.getLength();
			for (int i = 0; i < length; i++) {
				org.w3c.dom.Node node = nodeList.item(i);
				if (node instanceof IIOMetadataNode) {
					IIOMetadataNode metadataNode = (IIOMetadataNode) node;
					add(metadataNode);
				} else {
					throw new RuntimeException();
				}
			}
		}
	}
	
	@Override
	protected void paintComponent(Graphics g) {
		if (isImageLoaded) {
			g.drawImage(sourceImage, 0, 0, null);
		}
		g.drawLine(0, 0, 100, 100);
		g.drawOval(0, 0, getWidth(), getHeight());
	}
}
